﻿function register(ns)
{
    // from http://weblogs.asp.net/mschwarz/archive/2005/08/26/423699.aspx
    var nsParts = ns.split(".");
    var root = window;

    for(var i=0; i<nsParts.length; i++)
    {
        root = (root[nsParts[i]] = root[nsParts[i]] || {});
    }
}

register("Gw.Core");

Gw.Core.Tools = {
    InvertArray : function(array) {
        var inverted = new Array();
        switch (typeof array)
        {
            case "string":
                for (var i = 0; i < array.length; i++) inverted[array.charAt(i)] = i;
                break;
            default:
                for (var i in array) inverted[array[i]] = i;
                break;
        }
        return inverted;
    },
    
    UrlEncode : function(str) {
        return escape(str.replace(/%/g, '%25').replace(/\+/g, '%2B')).replace(/%25/g, '%');
    },
    
    HtmlEncode : function(str) {
        var div = document.createElement('div');
        var text = document.createTextNode(str);
        div.appendChild(text);
        return div.innerHTML;
    },
    
    QueryString : function(querystring) {
        var result = new Array();
        var params = querystring.replace(/\+/g, ' ').split('&');
        for (var i = 0; i < params.length; i++)
        {
            var keyValue = params[i].split('=');
            result[keyValue[0]] = keyValue[1];
        }
        
        return result;
    }(window.location.search.substr(1))
};

Gw.Core.Language = 'en';
Gw.Core.Translate = function(from, to, language) {

    if (!from) return false;
    
    if (!Gw.Core.Translate.Table)
        Gw.Core.Translate.Table = new Array();

    switch (typeof from)
    {
        case "string":
            language = language || Gw.Core.Language;
            var translations = Gw.Core.Translate.Table[language];
            if (!translations)
            {
                translations = new Array();
                Gw.Core.Translate.Table[language] = translations;
            }
            if (!to) return translations[from] || from;
            translations[from] = to;
            break;
            
        default:
            to = to || new Array();
            var result = new Array();
            for (var i in from) result[i] = Gw.Core.Translate(from[i], to[i], language);
            return result;
    }
};

Gw.Core.Professions = ['None', 'Warrior', 'Ranger', 'Monk', 'Necromancer', 'Mesmer', 'Elementalist', 'Assassin', 'Ritualist', 'Paragon', 'Dervish'];
Gw.Core.ShortProfessions = ['*', 'W', 'R', 'Mo', 'N', 'Me', 'E', 'A', 'Rt', 'P', 'D'];
Gw.Core.Attributes = ["Fast Casting", "Illusion Magic", "Domination Magic", "Inspiration Magic", "Blood Magic", "Death Magic", "Soul Reaping", "Curses", "Air Magic", "Earth Magic", "Fire Magic", "Water Magic", "Energy Storage", "Healing Prayers", "Smiting Prayers", "Protection Prayers", "Divine Favor", "Strength", "Axe Mastery", "Hammer Mastery", "Swordsmanship", "Tactics", "Beast Mastery", "Expertise", "Wilderness Survival", "Marksmanship", "?", "?", "?", "Dagger Mastery", "Deadly Arts", "Shadow Arts", "Communing", "Restoration Magic", "Channeling Magic", "Critical Strikes", "Spawning Power", "Spear Mastery", "Command", "Motivation", "Leadership", "Scythe Mastery", "Wind Prayers", "Earth Prayers", "Mysticism"];

Gw.Core.Base64Stream = function(code) {
    this.stream = code || "";
    this.mode = code ? "read" : "write";
    
    this.position = 0;
    this.buffer = 0;
    this.bufferLength = 0;
    
    return this;
}

Gw.Core.Base64Stream.prototype = {
    base64Chars : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
    //             0123456789012345678901234567890123456789012345678901234567890123
    //             0         1         2         3         4         5         6

    reverseBase64Chars : Gw.Core.Tools.InvertArray("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"),

    read : function(bits) {
        if (this.mode != "read") return false;
        
        // Number of bits not yet in buffer
        var needed = bits - this.bufferLength;
        // Read packets of 6 bits from stream
        while (needed > 0 && this.position < this.stream.length) {
            var next = this.stream.charAt(this.position++);
            var nextValue = this.reverseBase64Chars[next];
            this.buffer |= (nextValue << this.bufferLength);
            this.bufferLength += 6;
            needed -= 6;
        }

        // extract bits from buffer
        var result = this.buffer & ((1 << bits) - 1)
        this.buffer >>= bits;
        this.bufferLength -= bits;
      
        return result;
    },

    write : function(bits, value) {
        if (this.mode != "write") return false;

        // crop value
        value = value & ((1 << bits) - 1);

        // Write packets of 6 bits to buffer
        while (bits > 0) {
            var consumedBits = 6 - this.bufferLength;
            if (consumedBits > bits) consumedBits = bits;

            this.buffer |= (value & ((1 << consumedBits) - 1)) << this.bufferLength;
            this.bufferLength += consumedBits;
            
            bits -= consumedBits;
            value >>= consumedBits;
            
            if (this.bufferLength == 6) this.flush();
        }
    },

    flush : function() {
        if (this.mode != "write") return false;
        if (this.bufferLength == 0) return;
        if (this.bufferLength < 6) return this.write(6 - this.bufferLength, 0);
        this.stream += this.base64Chars.charAt(this.buffer);
        this.buffer = 0;
        this.bufferLength = 0;
    }
};
